package com.example.lib_mvp.views;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;

import com.example.lib_mvp.R;
import com.tjf.lib_utils.LogsUtils;

import java.util.HashMap;
import java.util.Map;

public class EqualizerView extends View {
    private static final String TAG = "EqualizerView";
    private int mWidth, mHeight;
    private int mMinHeight = 600;
    private float circleTextSize;
    private int circleTextColor;
    /**
     * 圆圈半径大小
     */
    private float circleRadius;
    /**
     * x轴文本数字
     */
    private float xTextSize;
    private int xSelectColor, xUnSelectColor;

    /**
     * 左右边距
     */
    private int marginLR;

    /**
     * dB宽度
     */
    private int mDbSize;

    /**
     * dB X轴步长
     */
    private int xAxialStep;

    /**
     * 画笔
     */
    private Paint mPaint;

    /**
     * X轴值,dB
     */
    private int[] yAxialVal = new int[]{10, 5, 0, -5, -10};
    /**
     * Y轴值，Hz
     */
    private int[] xAxialVal = new int[]{32, 62, 125, 250, 500, 1, 2, 4, 8, 16};
    /**
     * 当前选中的Hz Bar，-1表示未选中
     */
    private int currentSelectBarIndex = -1;
    /**
     * dB条数量
     */
    private int maxDbBarNum = 0;

    private Map<Integer, Integer> dBAndHzMap = new HashMap<>();
    private Map<Integer, Integer> dBAndHzMapBar = new HashMap<>();
    private float startY;  //在屏幕上滑动调节dB时，开始的Y轴值
    private float touchRange;  //屏幕的高，因为涉及到横竖屏切换，到时候会取小的值
    /**
     * 当前点击选中的Hz对应的dB值
     */
    private int currentDb = 0;

    public EqualizerView(Context context) {
        this(context, null);
    }

    public EqualizerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EqualizerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.EqualizerView);

        circleTextSize = a.getDimension(R.styleable.EqualizerView_evCircleTextSize, dip2px(getContext(), 14));
        circleTextColor = a.getColor(R.styleable.EqualizerView_evCircleTextColor, Color.BLACK);
        circleRadius = a.getDimension(R.styleable.EqualizerView_svCircleRadius, 20);
        xTextSize = a.getDimension(R.styleable.EqualizerView_evXTextSize, dip2px(getContext(), 14));
        xSelectColor = a.getColor(R.styleable.EqualizerView_evXSelectColor, Color.parseColor("#7875FF"));
        xUnSelectColor = a.getColor(R.styleable.EqualizerView_evXUnSelectColor, Color.parseColor("#FFFFFF"));
        marginLR = a.getInt(R.styleable.EqualizerView_evLRMargin, 50);

        a.recycle();
        mPaint = new Paint();
        //设置画笔的颜色
        mPaint.setColor(Color.BLACK);
        //设置抗锯齿
        mPaint.setAntiAlias(true);
        initXY(xAxialVal, yAxialVal, new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
        //下面使回调onkeydown事件
        setFocusableInTouchMode(true); //确保能接收到触屏事件
        setFocusable(true); //确保我们的View能获得输入焦点
    }

    private void initXY(int[] xAxialVal, int[] yAxialVal, int[] defaultYVal) {
        if (xAxialVal.length != defaultYVal.length) {
            throw new IllegalArgumentException("Y坐标值个数不匹配X坐标个数");
        }
        int y = yAxialVal[0] - yAxialVal[yAxialVal.length - 1];
        maxDbBarNum = y + 1;
        for (int i = 0; i < xAxialVal.length; i++) {
            dBAndHzMap.put(i, defaultYVal[i]);
            int bar = calculateDbBum(defaultYVal[i]) + 1;
            LogsUtils.i("kuai==" + bar);
            dBAndHzMapBar.put(i, bar);
        }
    }

    /**
     * 转换db值的  占整个白色bar 区域 20份的多少的
     * 计算db数量块
     *
     * @param dbValue
     * @return
     */
    private int calculateDbBum(int dbValue) {
        int up = yAxialVal[0];
        int down = yAxialVal[yAxialVal.length - 1];
        int val;
        if (dbValue >= down && dbValue <= up) {
            val = dbValue - down;
        } else {
            throw new IllegalArgumentException("dB 值越界：" + dbValue);
        }
        return val;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width;
        int height;
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = widthSize * 1 / 2;
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = heightSize * 1 / 2;
        }
        if (height < mMinHeight) { // 适配大屏问题
            height = mMinHeight;
        }
        setMeasuredDimension(width, height);
    }

    // 计算高度宽度
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = getWidth();
        mHeight = getHeight();
        int size = xAxialVal.length + 1;
        mDbSize = (int) ((mWidth - 2 * marginLR - 4 * circleRadius - 20) / (size * 2)); // dB块宽度
        xAxialStep = (int) ((mWidth - 2 * marginLR - 4 * circleRadius - 20) / size);
        Log.i(TAG, "mWidth:" + mWidth + ",mHeight:" + mHeight + ",xAxialStep:" + xAxialStep + ",mDbSize:" + mDbSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize(xTextSize);
        mPaint.setStyle(Paint.Style.FILL);

        // 绘制dB单位
        drawTextCentered("dB", marginLR + circleRadius, marginLR, canvas);

        // 绘制Y轴坐标
        drawYAxis(canvas);

        // 绘制X轴坐标
        drawXAxis(canvas);

        // 绘制Hz单位
        drawTextRightAligned("Hz", getWidth() - marginLR + 20, mHeight - marginLR + 40, canvas);
    }

    private void drawTextCentered(String text, float centerX, float baselineY, Canvas canvas) {
        mPaint.setColor(Color.BLACK);
        float textWidth = mPaint.measureText(text);
        canvas.drawText(text, centerX - textWidth / 2, baselineY, mPaint);
    }

    private void drawTextRightAligned(String text, float rightX, float baselineY, Canvas canvas) {
        float textWidth = mPaint.measureText(text);
        canvas.drawText(text, rightX - textWidth, baselineY, mPaint);
    }

    private void drawYAxis(Canvas canvas) {
        int yStart = marginLR + 20;
        int yStep = (mHeight - 2 * marginLR - 40) / (yAxialVal.length - 1);
        for (int i = 0; i < yAxialVal.length; i++) {
            mPaint.setStyle(Paint.Style.FILL);
            // 绘制Y轴刻度线
            // canvas.drawLine(marginLR + 2 * circleRadius, yStart, getWidth() - marginLR, yStart, mPaint);

            // 绘制Y轴刻度值
            drawTextCentered(String.valueOf(yAxialVal[i]), marginLR + circleRadius, yStart + circleTextSize / 2, canvas);
            yStart += yStep;
        }
    }

    private void drawXAxis(Canvas canvas) {
        int xStart = (int) (marginLR + 2 * circleRadius + 30);
        int xStep = (int) ((getWidth() - 2 * marginLR - 4 * circleRadius - 20) / (xAxialVal.length));
        int whiteBarHeight = (int) ((mHeight - 2 * marginLR - 40) * (22.0f / MAX_DB_BAR_NUM));

        for (int i = 0; i < xAxialVal.length; i++) {
            int left = xStart + i * xStep + 30;
            // 绘制未滑动的白色背景柱状条
            drawBar(left, mHeight - marginLR, (int) (xStep / 2.6f), whiteBarHeight, xUnSelectColor, canvas);
            mPaint.setColor(xSelectColor);
            // 绘制滑动的蓝色柱状条
            int dbVal = dBAndHzMapBar.get(i);
            // 计算滑动的柱状条高度，确保不超过白色背景条
            int barHeight = (int) ((mHeight - 2 * marginLR - 40) * ((float) dbVal / MAX_DB_BAR_NUM));
            int top = mHeight - marginLR - barHeight;
            // 限制顶部位置不超过白色背景条的顶部
            top = Math.max(top, mHeight - marginLR - whiteBarHeight);
            // 限制底部位置不超过白色背景条的底部
            top = Math.min(top, mHeight - marginLR);
            canvas.drawRoundRect(left, top, xStart + i * xStep + xStep / 1.3f,
                    mHeight - marginLR, 16, 16, mPaint);

            // 绘制滑块指示器
            drawSliderIndicator(left, top, (int) (xStep / 2.6f), barHeight, canvas);

            // 绘制X轴刻度值
            drawTextCentered(xAxialVal[i] >= 32 ? String.valueOf(xAxialVal[i]) : xAxialVal[i] + "K",
                    xStart + i * xStep + xStep / 2, mHeight - marginLR + 40, canvas);
        }
    }

    private void drawBar(float left, float bottom, int barWidth, int barHeight, int color, Canvas canvas) {
        mPaint.setColor(color);
        canvas.drawRoundRect(left, bottom - barHeight, left + barWidth, bottom, 16, 16, mPaint);
    }

    private void drawSliderIndicator(float left, float top, int barWidth, int barHeight, Canvas canvas) {
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(left + barWidth / 2, top - 20, 30, mPaint);
        mPaint.setColor(Color.parseColor("#32C5FF"));
        canvas.drawCircle(left + barWidth / 2, top - 20, 20, mPaint);
    }


    private static final int MIN_DB = -10;
    private static final int MAX_DB = 10;
    private static final int MAX_DB_BAR_NUM = MAX_DB - MIN_DB; // 20

    private boolean isTouch = false;

    public void setTouch(boolean touch) {
        isTouch = touch;
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!isTouch) {
            return true;
        }
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        int left = marginLR + 2 * (int) circleRadius + 20;
        int top = marginLR + 20;
        int length = xAxialVal.length;
        int barWidth = (int) ((getWidth() - 2 * marginLR - 4 * circleRadius - 20) / length);
        int bottom = mHeight - marginLR;
        int whiteBarHeight = (int) ((mHeight - 2 * marginLR - 40) * (22.0f / MAX_DB_BAR_NUM));
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startY = ev.getY();
                touchRange = whiteBarHeight; // 柱状图的高度范围
                Log.i(TAG, "onTouchEvent, touchRange:" + touchRange);

                for (int i = 0; i < length; i++) {
                    Rect rect = new Rect(left, top, left + barWidth, bottom);
                    // 精确点击位置
                    if (rect.contains(x, y)) {
                        currentSelectBarIndex = i;
                        // 计算点击位置相对于白色进度条顶部的高度
                        int clickHeight = bottom - y;
                        // 确保点击位置在白色进度条的范围内
                        if (clickHeight >= 0 && clickHeight <= whiteBarHeight) {
                            // 将点击高度映射到 dB 值
                            float fraction = (float) clickHeight / whiteBarHeight;
                            currentDb = (int) Math.round(fraction * MAX_DB_BAR_NUM) + MIN_DB;
                            currentDb = Math.min(Math.max(currentDb, MIN_DB), MAX_DB); // 确保初始值在-10到10之间
                            dBAndHzMap.put(currentSelectBarIndex, currentDb); // 更新 dBAndHzMapBar

                            int bar = calculateDbBum(currentDb) + 1;
                            LogsUtils.i("onTouchEvent==" + bar);
                            dBAndHzMapBar.put(currentSelectBarIndex, bar);
                            invalidate();
                        }
                        break;
                    }
                    left += barWidth;
                }
                break;

            case MotionEvent.ACTION_MOVE:
                updateDb(ev);
                break;

            case MotionEvent.ACTION_UP:
                break;

            default:
                break;
        }
        return true;
    }

    ValueAnimator animator;

    private void updateDb(MotionEvent ev) {
        if (currentSelectBarIndex != -1) {
            float deltaY = startY - ev.getY();
            float fraction = deltaY / touchRange;
            fraction = Math.max(-1, Math.min(1, fraction));
            int targetDb = currentDb + (int) (fraction * MAX_DB_BAR_NUM);
            targetDb = Math.min(Math.max(targetDb, MIN_DB), MAX_DB);

            if (animator != null && animator.isRunning()) {
                animator.cancel();
            }

            animator = ValueAnimator.ofInt(currentDb, targetDb);
            animator.setDuration(30); // 动画持续时间 100 毫秒
            animator.setInterpolator(new LinearInterpolator());
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int animatedValue = (int) animation.getAnimatedValue();
                    int bar = calculateDbBum(animatedValue) + 1;
                    LogsUtils.i("onTouchEvent==" + bar);
                    dBAndHzMapBar.put(currentSelectBarIndex, bar);
                    dBAndHzMap.put(currentSelectBarIndex, animatedValue);
                    currentDb = animatedValue;
                    invalidate();
                }
            });
            animator.start();
        }
    }


    /**
     * 获取基线y轴坐标
     *
     * @param circleR
     * @return
     */
    public int getBaseLineY(int circleR) {
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float textTop = fontMetrics.top;
        float textBottom = fontMetrics.bottom;
        float contentBottom = circleR / 2;
        int baseLineY = (int) (contentBottom - textTop / 2 - textBottom / 2);
        return baseLineY;
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 向做移动音量条
     */
    public void moveLeft() {
        if (currentSelectBarIndex == 0) {
            return;
        }
        currentSelectBarIndex--;
        invalidate();
    }

    /**
     * 向右移动音量条
     */
    public void moveRight() {
        if (currentSelectBarIndex == xAxialVal.length - 1) {
            return;
        }
        currentSelectBarIndex++;
        invalidate();
    }

    /**
     * 增加音量
     */
    public void moveUp() {
        if (currentSelectBarIndex == -1) {
            return;
        }
        int defaultYVal = dBAndHzMapBar.get(currentSelectBarIndex);
        if (defaultYVal == maxDbBarNum) {
            return;
        }
        defaultYVal++;
        dBAndHzMapBar.put(currentSelectBarIndex, defaultYVal);
        invalidate();
    }

    /**
     * 降低音量
     */
    public void moveDown() {
        if (currentSelectBarIndex == -1) {
            return;
        }
        int defaultYVal = dBAndHzMapBar.get(currentSelectBarIndex);
        if (defaultYVal == 1) { // 保留最后一隔音量
            return;
        }
        defaultYVal--;
        dBAndHzMapBar.put(currentSelectBarIndex, defaultYVal);
        Log.i(TAG, "触发了moveDown");
        invalidate();
    }

    /**
     * 设置默认选中的柱状条
     *
     * @param currentSelectBarIndex
     */
    public void setCurrentSelectBarIndex(int currentSelectBarIndex) {
        this.currentSelectBarIndex = currentSelectBarIndex;
        invalidate();
    }

    /**
     * 整体修改
     *
     * @param dbValue 指定值，不能超出y轴范围，可以为正负
     */
    public void setDbVal(int dbValue) {
        int val = calculateDbBum(dbValue);
        for (int i = 0; i < xAxialVal.length; i++) {
            dBAndHzMap.put(i, val + 1);
        }
        invalidate();
    }

    /**
     * 重置
     */
    public void reset() {
        setDbVal(0);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_UP: // 向上
                Log.e(TAG, "————－向上－－－－－");
                moveUp();
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN: // 向下
                Log.e(TAG, "－－－－－向下－－－－－");
                moveDown();
                break;
            case KeyEvent.KEYCODE_DPAD_LEFT: // 向左
                Log.e(TAG, "－－－－－向左－－－－－");
                moveLeft();
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT: // 向右
                Log.e(TAG, "－－－－－向右－－－－－");
                moveRight();
                break;
            case KeyEvent.KEYCODE_ENTER: // 确定
                Log.e(TAG, "————－确定－－－－－");
                break;
        }
        return super.onKeyDown(keyCode, event);
    }

    /**
     * 设置数据
     *
     * @param xVal        X坐标
     * @param yVal        y坐标
     * @param defaultYVal y坐标默认值
     */
    public void setXYData(int[] xVal, int[] yVal, int[] defaultYVal) {
        this.xAxialVal = xVal;
        this.yAxialVal = yVal;
        int size = xVal.length + 1;
        mDbSize = (int) ((mWidth - 2 * marginLR - 4 * circleRadius - 20) / (size * 2)); // dB块宽度
        xAxialStep = (int) ((mWidth - 2 * marginLR - 4 * circleRadius - 20) / size);
        initXY(xVal, yVal, defaultYVal);
        invalidate();
    }

    /**
     * 设置Y坐标值数据
     *
     * @param defaultYVal y坐标默认值
     */
    public void setYVal(int[] defaultYVal) {
        initXY(this.xAxialVal, this.yAxialVal, defaultYVal);
        invalidate();
    }

    /**
     * 获取d和Hz映射值
     *
     * @return
     */
    public Map<Integer, Integer> getDbAndHzMap() {
        int down = yAxialVal[yAxialVal.length - 1];
        Map<Integer, Integer> temp = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : dBAndHzMap.entrySet()) {
            Integer key = entry.getKey();
            Integer value = entry.getValue();
//            int realVal = value + down - 1;
            temp.put(key, value);
        }
        return temp;
    }

    /**
     * 获取d和Hz映射值
     *
     * @return
     */
    public Map<Integer, Integer> getDbAndHzMapBar() {
        int down = yAxialVal[yAxialVal.length - 1];
        Map<Integer, Integer> temp = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : dBAndHzMapBar.entrySet()) {
            Integer key = entry.getKey();
            Integer value = entry.getValue();
            int realVal = value + down;
            temp.put(key, realVal);
        }
        return temp;
    }
}